home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume15 / stevie / part02 < prev    next >
Encoding:
Internet Message Format  |  1988-06-05  |  44.3 KB

  1. Subject:  v15i038:  Stevie, an "aspiring" VI clone for Unix, OS/2, Amiga, Part02/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: onecom!wldrdg!tony (Tony Andrews)
  7. Posting-number: Volume 15, Issue 38
  8. Archive-name: stevie/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 2 (of 4)."
  17. # Contents:  cmdline.c edit.c help.c main.c misccmds.c
  18. # Wrapped by rsalz@fig.bbn.com on Sun Jun  5 11:45:43 1988
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'cmdline.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'cmdline.c'\"
  22. else
  23. echo shar: Extracting \"'cmdline.c'\" \(11004 characters\)
  24. sed "s/^X//" >'cmdline.c' <<'END_OF_FILE'
  25. X/*
  26. X * STevie - ST editor for VI enthusiasts.   ...Tim Thompson...twitch!tjt...
  27. X *
  28. X * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  29. X *
  30. X */
  31. X
  32. X#include "stevie.h"
  33. X
  34. static    char    *altfile = NULL;    /* alternate file */
  35. static    int    altline;        /* line # in alternate file */
  36. X
  37. static    char    *nowrtmsg = "No write since last change (use ! to override)";
  38. X
  39. extern    char    **files;        /* used for "n" and "rew" */
  40. extern    int    numfiles, curfile;
  41. X
  42. X/*
  43. X * The next two variables contain the bounds of any range given in a
  44. X * command. If no range was given, both contain null line pointers.
  45. X * If only a single line was given, u_pos will contain a null line
  46. X * pointer.
  47. X */
  48. static    LPTR    l_pos, u_pos;
  49. X
  50. static    bool_t    interactive;    /* TRUE if we're reading a real command line */
  51. X
  52. X#define    CMDSZ    100        /* size of the command buffer */
  53. X
  54. static    bool_t    doecmd();
  55. static    void    badcmd(), doshell(), get_range();
  56. static    LPTR    *get_line();
  57. X
  58. X#ifdef    MEGAMAX
  59. overlay "cmdline"
  60. X#endif
  61. X
  62. X/*
  63. X * readcmdline() - accept a command line starting with ':', '/', or '?'
  64. X *
  65. X * readcmdline() accepts and processes colon commands and searches. If
  66. X * 'cmdline' is null, the command line is read here. Otherwise, cmdline
  67. X * points to a complete command line that should be used. This is used
  68. X * in main() to handle initialization commands in the environment variable
  69. X * "EXINIT".
  70. X */
  71. void
  72. readcmdline(firstc, cmdline)
  73. int    firstc;        /* either ':', '/', or '?' */
  74. char    *cmdline;    /* optional command string */
  75. X{
  76. X    int c;
  77. X    char buff[CMDSZ];
  78. X    char *p, *q, *cmd, *arg;
  79. X
  80. X    /*
  81. X     * Clear the range variables.
  82. X     */
  83. X    l_pos.linep = (struct line *) NULL;
  84. X    u_pos.linep = (struct line *) NULL;
  85. X
  86. X    interactive = (cmdline == NULL);
  87. X
  88. X    if (interactive)
  89. X        gotocmd(1,1,firstc);
  90. X    p = buff;
  91. X    if ( firstc != ':' )
  92. X        *p++ = firstc;
  93. X
  94. X    if (interactive) {
  95. X        /* collect the command string, handling '\b' and @ */
  96. X        for ( ; ; ) {
  97. X            c = vgetc();
  98. X            if ( c=='\n'||c=='\r'||c==EOF )
  99. X                break;
  100. X            if ( c=='\b' ) {
  101. X                if ( p > buff ) {
  102. X                    p--;
  103. X                    /* this is gross, but it relies
  104. X                     * only on 'gotocmd'
  105. X                     */
  106. X                    gotocmd(1,0,firstc==':'?':':0);
  107. X                    for ( q=buff; q<p; q++ )
  108. X                        outchar(*q);
  109. X                } else {
  110. X                    msg("");
  111. X                    return;        /* back to cmd mode */
  112. X                }
  113. X                continue;
  114. X            }
  115. X            if ( c=='@' ) {
  116. X                p = buff;
  117. X                gotocmd(1,1,firstc);
  118. X                continue;
  119. X            }
  120. X            outchar(c);
  121. X            *p++ = c;
  122. X        }
  123. X        *p = '\0';
  124. X    } else {
  125. X        if (strlen(cmdline) > CMDSZ-2)    /* should really do something */
  126. X            return;            /* better here... */
  127. X        strcpy(p, cmdline);
  128. X    }
  129. X
  130. X    /* skip any initial white space */
  131. X    for ( cmd = buff; *cmd != NUL && isspace(*cmd); cmd++ )
  132. X        ;
  133. X
  134. X    /* search commands */
  135. X    c = *cmd;
  136. X    if ( c == '/' || c == '?' ) {
  137. X        cmd++;
  138. X        if ( *cmd == c ) {
  139. X            /* the command was '//' or '??' */
  140. X            repsearch();
  141. X            return;
  142. X        }
  143. X        /* If there is a matching '/' or '?' at the end, toss it */
  144. X        p = strchr(cmd, NUL);
  145. X        if ( *(p-1) == c && *(p-2) != '\\' )
  146. X            *(p-1) = NUL;
  147. X        dosearch((c == '/') ? FORWARD : BACKWARD, cmd);
  148. X        return;
  149. X    }
  150. X
  151. X    /*
  152. X     * Parse a range, if present (and update the cmd pointer).
  153. X     */
  154. X    get_range(&cmd);
  155. X
  156. X    /* isolate the command and find any argument */
  157. X    for ( p=cmd; *p != NUL && ! isspace(*p); p++ )
  158. X        ;
  159. X    if ( *p == NUL )
  160. X        arg = NULL;
  161. X    else {
  162. X        *p = NUL;
  163. X        for (p++; *p != NUL && isspace(*p) ;p++)
  164. X            ;
  165. X        arg = p;
  166. X        if ( *arg == '\0' )
  167. X            arg = NULL;
  168. X    }
  169. X    if ( strcmp(cmd,"q!")==0 )
  170. X        getout();
  171. X    if ( strcmp(cmd,"q")==0 ) {
  172. X        if ( Changed )
  173. X            emsg(nowrtmsg);
  174. X        else
  175. X            getout();
  176. X        return;
  177. X    }
  178. X    if ( strcmp(cmd,"w")==0 ) {
  179. X        if ( arg == NULL ) {
  180. X            if (Filename != NULL) {
  181. X                writeit(Filename, &l_pos, &u_pos);
  182. X                UNCHANGED;
  183. X            } else
  184. X                emsg("No output file");
  185. X        }
  186. X        else
  187. X            writeit(arg, &l_pos, &u_pos);
  188. X        return;
  189. X    }
  190. X    if ( strcmp(cmd,"wq")==0 ) {
  191. X        if (Filename != NULL) {
  192. X            if ( writeit(Filename, NULL, NULL) )
  193. X                getout();
  194. X        } else
  195. X            emsg("No output file");
  196. X        return;
  197. X    }
  198. X    if ( strcmp(cmd, "x") == 0 ) {
  199. X        if (Changed) {
  200. X            if (Filename != NULL) {
  201. X                if (!writeit(Filename, NULL, NULL))
  202. X                    return;
  203. X            } else {
  204. X                emsg("No output file");
  205. X                return;
  206. X            }
  207. X        }
  208. X        getout();
  209. X    }
  210. X    if ( strcmp(cmd,"f")==0 && arg==NULL ) {
  211. X        fileinfo();
  212. X        return;
  213. X    }
  214. X    if ( *cmd == 'n' ) {
  215. X        if ( (curfile + 1) < numfiles ) {
  216. X            /*
  217. X             * stuff ":e[!] FILE\n"
  218. X             */
  219. X            stuffin(":e");
  220. X            if (cmd[1] == '!')
  221. X                stuffin("!");
  222. X            stuffin(" ");
  223. X            stuffin(files[++curfile]);
  224. X            stuffin("\n");
  225. X        } else
  226. X            emsg("No more files!");
  227. X        return;
  228. X    }
  229. X    if ( *cmd == 'p' ) {
  230. X        if ( curfile > 0 ) {
  231. X            /*
  232. X             * stuff ":e[!] FILE\n"
  233. X             */
  234. X            stuffin(":e");
  235. X            if (cmd[1] == '!')
  236. X                stuffin("!");
  237. X            stuffin(" ");
  238. X            stuffin(files[--curfile]);
  239. X            stuffin("\n");
  240. X        } else
  241. X            emsg("No more files!");
  242. X        return;
  243. X    }
  244. X    if ( strncmp(cmd, "rew", 3) == 0) {
  245. X        if (numfiles <= 1)        /* nothing to rewind */
  246. X            return;
  247. X        curfile = 0;
  248. X        /*
  249. X         * stuff ":e[!] FILE\n"
  250. X         */
  251. X        stuffin(":e");
  252. X        if (cmd[3] == '!')
  253. X            stuffin("!");
  254. X        stuffin(" ");
  255. X        stuffin(files[0]);
  256. X        stuffin("\n");
  257. X        return;
  258. X    }
  259. X    if ( strcmp(cmd,"e") == 0 || strcmp(cmd,"e!") == 0 ) {
  260. X        doecmd(arg, cmd[1] == '!');
  261. X        return;
  262. X    }
  263. X    if ( strcmp(cmd,"f") == 0 ) {
  264. X        Filename = strsave(arg);
  265. X        filemess("");
  266. X        return;
  267. X    }
  268. X    if ( strcmp(cmd,"r") == 0 || strcmp(cmd,".r") == 0 ) {
  269. X        if ( arg == NULL ) {
  270. X            badcmd();
  271. X            return;
  272. X        }
  273. X        if (readfile(arg, Curschar, 1)) {
  274. X            emsg("Can't open file");
  275. X            return;
  276. X        }
  277. X        updatescreen();
  278. X        CHANGED;
  279. X        return;
  280. X    }
  281. X    if ( strcmp(cmd,".=")==0 ) {
  282. X        char messbuff[80];
  283. X        sprintf(messbuff,"line %d", cntllines(Filemem,Curschar));
  284. X        msg(messbuff);
  285. X        return;
  286. X    }
  287. X    if ( strcmp(cmd,"$=")==0 ) {
  288. X        char messbuff[8];
  289. X        sprintf(messbuff, "%d", cntllines(Filemem, Fileend)-1);
  290. X        msg(messbuff);
  291. X        return;
  292. X    }
  293. X    if ( strncmp(cmd,"ta", 2) == 0 ) {
  294. X        dotag(arg, cmd[2] == '!');
  295. X        return;
  296. X    }
  297. X    if ( strcmp(cmd,"set")==0 ) {
  298. X        doset(arg, interactive);
  299. X        return;
  300. X    }
  301. X    if ( strcmp(cmd,"help")==0 ) {
  302. X        if (help()) {
  303. X            screenclear();
  304. X            updatescreen();
  305. X        }
  306. X        return;
  307. X    }
  308. X    if ( strcmp(cmd, "version") == 0) {
  309. X        extern    char    *Version;
  310. X
  311. X        msg(Version);
  312. X        return;
  313. X    }
  314. X    if ( strcmp(cmd, "sh") == 0) {
  315. X        doshell();
  316. X        return;
  317. X    }
  318. X    /*
  319. X     * If we got a line, but no command, then go to the line.
  320. X     */
  321. X    if (*cmd == NUL && l_pos.linep != NULL) {
  322. X        *Curschar = l_pos;
  323. X        cursupdate();
  324. X        return;
  325. X    }
  326. X
  327. X    badcmd();
  328. X}
  329. X
  330. X/*
  331. X * get_range - parse a range specifier
  332. X *
  333. X * Ranges are of the form:
  334. X *
  335. X * addr[,addr]
  336. X *
  337. X * where 'addr' is:
  338. X *
  339. X * $  [+- NUM]
  340. X * 'x [+- NUM]    (where x denotes a currently defined mark)
  341. X * .  [+- NUM]
  342. X * NUM
  343. X *
  344. X * The pointer *cp is updated to point to the first character following
  345. X * the range spec. If an initial address is found, but no second, the
  346. X * upper bound is equal to the lower.
  347. X */
  348. static void
  349. get_range(cp)
  350. char    **cp;
  351. X{
  352. X    LPTR    *l;
  353. X    char    *p;
  354. X
  355. X    if ((l = get_line(cp)) == NULL)
  356. X        return;
  357. X
  358. X    l_pos = *l;
  359. X
  360. X    for (p = *cp; *p != NUL && isspace(*p) ;p++)
  361. X        ;
  362. X
  363. X    *cp = p;
  364. X
  365. X    if (*p != ',') {        /* is there another line spec ? */
  366. X        u_pos = l_pos;
  367. X        return;
  368. X    }
  369. X
  370. X    *cp = ++p;
  371. X
  372. X    if ((l = get_line(cp)) == NULL) {
  373. X        u_pos = l_pos;
  374. X        return;
  375. X    }
  376. X
  377. X    u_pos = *l;
  378. X}
  379. X
  380. static LPTR *
  381. get_line(cp)
  382. char    **cp;
  383. X{
  384. X    static    LPTR    pos;
  385. X    LPTR    *lp;
  386. X    char    *p, c;
  387. X    int    lnum;
  388. X
  389. X    pos.index = 0;        /* shouldn't matter... check back later */
  390. X
  391. X    p = *cp;
  392. X    /*
  393. X     * Determine the basic form, if present.
  394. X     */
  395. X    switch (c = *p++) {
  396. X
  397. X    case '$':
  398. X        pos.linep = Fileend->linep->prev;
  399. X        break;
  400. X
  401. X    case '.':
  402. X        pos.linep = Curschar->linep;
  403. X        break;
  404. X
  405. X    case '\'':
  406. X        if ((lp = getmark(*p++)) == NULL) {
  407. X            emsg("Unknown mark");
  408. X            return (LPTR *) NULL;
  409. X        }
  410. X        pos = *lp;
  411. X        break;
  412. X
  413. X    case '0': case '1': case '2': case '3': case '4':
  414. X    case '5': case '6': case '7': case '8': case '9':
  415. X        for (lnum = c - '0'; isdigit(*p) ;p++)
  416. X            lnum = (lnum * 10) + (*p - '0');
  417. X
  418. X        pos = *gotoline(lnum);
  419. X        break;
  420. X
  421. X    default:
  422. X        return (LPTR *) NULL;
  423. X    }
  424. X
  425. X    while (*p != NUL && isspace(*p))
  426. X        p++;
  427. X
  428. X    if (*p == '-' || *p == '+') {
  429. X        bool_t    neg = (*p++ == '-');
  430. X
  431. X        for (lnum = 0; isdigit(*p) ;p++)
  432. X            lnum = (lnum * 10) + (*p - '0');
  433. X
  434. X        if (neg)
  435. X            lnum = -lnum;
  436. X
  437. X        pos = *gotoline( cntllines(Filemem, &pos) + lnum );
  438. X    }
  439. X
  440. X    *cp = p;
  441. X    return &pos;
  442. X}
  443. X
  444. static void
  445. badcmd()
  446. X{
  447. X    if (interactive)
  448. X        emsg("Unrecognized command");
  449. X}
  450. X
  451. X#define    LSIZE    512    /* max. size of a line in the tags file */
  452. X
  453. X/*
  454. X * dotag(tag, force) - goto tag
  455. X */
  456. void
  457. dotag(tag, force)
  458. char    *tag;
  459. bool_t    force;
  460. X{
  461. X    FILE    *tp, *fopen();
  462. X    char    lbuf[LSIZE];
  463. X    char    *fname, *str;
  464. X
  465. X    if ((tp = fopen("tags", "r")) == NULL) {
  466. X        emsg("Can't open tags file");
  467. X        return;
  468. X    }
  469. X
  470. X    while (fgets(lbuf, LSIZE, tp) != NULL) {
  471. X    
  472. X        if ((fname = strchr(lbuf, TAB)) == NULL) {
  473. X            emsg("Format error in tags file");
  474. X            return;
  475. X        }
  476. X        *fname++ = '\0';
  477. X        if ((str = strchr(fname, TAB)) == NULL) {
  478. X            emsg("Format error in tags file");
  479. X            return;
  480. X        }
  481. X        *str++ = '\0';
  482. X
  483. X        if (strcmp(lbuf, tag) == 0) {
  484. X            if (doecmd(fname, force)) {
  485. X                stuffin(str);        /* str has \n at end */
  486. X                stuffin("\007");    /* CTRL('G') */
  487. X                fclose(tp);
  488. X                return;
  489. X            }
  490. X        }
  491. X    }
  492. X    emsg("tag not found");
  493. X    fclose(tp);
  494. X}
  495. X
  496. static    bool_t
  497. doecmd(arg, force)
  498. char    *arg;
  499. bool_t    force;
  500. X{
  501. X    int    line = 1;        /* line # to go to in new file */
  502. X
  503. X    if (!force && Changed) {
  504. X        emsg(nowrtmsg);
  505. X        return FALSE;
  506. X    }
  507. X    if ( arg != NULL ) {
  508. X        /*
  509. X         * First detect a ":e" on the current file. This is mainly
  510. X         * for ":ta" commands where the destination is within the
  511. X         * current file.
  512. X         */
  513. X        if (Filename != NULL && strcmp(arg, Filename) == 0) {
  514. X            if (!Changed || (Changed && !force))
  515. X                return TRUE;
  516. X        }
  517. X        if (strcmp(arg, "#") == 0) {    /* alternate */
  518. X            char    *s = Filename;
  519. X
  520. X            if (altfile == NULL) {
  521. X                emsg("No alternate file");
  522. X                return FALSE;
  523. X            }
  524. X            Filename = altfile;
  525. X            altfile  = s;
  526. X            line = altline;
  527. X            altline = cntllines(Filemem, Curschar);
  528. X        } else {
  529. X            altfile = Filename;
  530. X            altline = cntllines(Filemem, Curschar);
  531. X            Filename = strsave(arg);
  532. X        }
  533. X    }
  534. X    if (Filename == NULL) {
  535. X        emsg("No filename");
  536. X        return FALSE;
  537. X    }
  538. X
  539. X    /* clear mem and read file */
  540. X    freeall();
  541. X    filealloc();
  542. X    UNCHANGED;
  543. X
  544. X    readfile(Filename, Filemem, 0);
  545. X    *Topchar = *Curschar;
  546. X    if (line != 1) {
  547. X        stuffnum(line);
  548. X        stuffin("G");
  549. X    }
  550. X    setpcmark();
  551. X    updatescreen();
  552. X    return TRUE;
  553. X}
  554. X
  555. static void
  556. doshell()
  557. X{
  558. X    char    *sh, *getenv();
  559. X
  560. X    if ((sh = getenv("SHELL")) == NULL) {
  561. X        emsg("Shell variable not set");
  562. X        return;
  563. X    }
  564. X    gotocmd(TRUE, FALSE, 0);
  565. X
  566. X    if (system(sh) < 0) {
  567. X        emsg("Exec failed");
  568. X        return;
  569. X    }
  570. X
  571. X    wait_return();
  572. X}
  573. X
  574. void
  575. gotocmd(clr, fresh, firstc)
  576. bool_t  clr, fresh;
  577. char    firstc;
  578. X{
  579. X    int n;
  580. X
  581. X    windgoto(Rows-1,0);
  582. X    if ( clr )
  583. X        outstr(T_EL);        /* clear the bottom line */
  584. X    if ( firstc )
  585. X        outchar(firstc);
  586. X}
  587. X
  588. X/*
  589. X * msg(s) - displays the string 's' on the status line
  590. X */
  591. void
  592. msg(s)
  593. char *s;
  594. X{
  595. X    gotocmd(TRUE, TRUE, 0);
  596. X    outstr(s);
  597. X}
  598. X
  599. void
  600. smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  601. char    *s;
  602. int    a1, a2, a3, a4, a5, a6, a7, a8, a9;
  603. X{
  604. X    char    sbuf[80];
  605. X
  606. X    sprintf(sbuf, s, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  607. X    msg(sbuf);
  608. X}
  609. X
  610. X/*
  611. X * emsg() - display an error message
  612. X *
  613. X * Rings the bell, if appropriate, and calls message() to do the real work
  614. X */
  615. void
  616. emsg(s)
  617. char    *s;
  618. X{
  619. X    if (P(P_EB))
  620. X        beep();
  621. X    msg(s);
  622. X}
  623. X
  624. void
  625. wait_return()
  626. X{
  627. X    char    c;
  628. X
  629. X    outstr("Press RETURN to continue");
  630. X    do {
  631. X        c = vgetc();
  632. X    } while (c != '\r' && c != '\n');
  633. X
  634. X    screenclear();
  635. X    updatescreen();
  636. X}
  637. END_OF_FILE
  638. if test 11004 -ne `wc -c <'cmdline.c'`; then
  639.     echo shar: \"'cmdline.c'\" unpacked with wrong size!
  640. fi
  641. # end of 'cmdline.c'
  642. fi
  643. if test -f 'edit.c' -a "${1}" != "-c" ; then 
  644.   echo shar: Will not clobber existing file \"'edit.c'\"
  645. else
  646. echo shar: Extracting \"'edit.c'\" \(6480 characters\)
  647. sed "s/^X//" >'edit.c' <<'END_OF_FILE'
  648. X/*
  649. X * STevie - ST editor for VI enthusiasts.     ...Tim Thompson...twitch!tjt...
  650. X *
  651. X * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  652. X *
  653. X */
  654. X
  655. X#include "stevie.h"
  656. X
  657. X/*
  658. X * This flag is used to make auto-indent work right on lines where only
  659. X * a <RETURN> or <ESC> is typed. It is set when an auto-indent is done,
  660. X * and reset when any other editting is done on the line. If an <ESC>
  661. X * or <RETURN> is received, and did_ai is TRUE, the line is truncated.
  662. X */
  663. bool_t    did_ai = FALSE;
  664. X
  665. void
  666. edit()
  667. X{
  668. X    int c;
  669. X    char *p, *q;
  670. X
  671. X    Prenum = 0;
  672. X
  673. X    /* position the display and the cursor at the top of the file. */
  674. X    *Topchar = *Filemem;
  675. X    *Curschar = *Filemem;
  676. X    Cursrow = Curscol = 0;
  677. X
  678. X    for ( ;; ) {
  679. X
  680. X    /* Figure out where the cursor is based on Curschar. */
  681. X    cursupdate();
  682. X
  683. X    windgoto(Cursrow,Curscol);
  684. X
  685. X    c = vgetc();
  686. X
  687. X    if (State == NORMAL) {
  688. X
  689. X        /* We're in the normal (non-insert) mode. */
  690. X
  691. X        /* Pick up any leading digits and compute 'Prenum' */
  692. X        if ( (Prenum>0 && isdigit(c)) || (isdigit(c) && c!='0') ){
  693. X            Prenum = Prenum*10 + (c-'0');
  694. X            continue;
  695. X        }
  696. X        /* execute the command */
  697. X        normal(c);
  698. X        Prenum = 0;
  699. X
  700. X    } else {
  701. X
  702. X        switch (c) {    /* We're in insert mode */
  703. X
  704. X        case ESC:    /* an escape ends input mode */
  705. X
  706. X            set_want_col = TRUE;
  707. X
  708. X            /* Don't end up on a '\n' if you can help it. */
  709. X            if (gchar(Curschar) == NUL && Curschar->index != 0)
  710. X                dec(Curschar);
  711. X
  712. X            /*
  713. X             * The cursor should end up on the last inserted
  714. X             * character. This is an attempt to match the real
  715. X             * 'vi', but it may not be quite right yet.
  716. X             */
  717. X            if (Curschar->index != 0 && !endofline(Curschar))
  718. X                dec(Curschar);
  719. X
  720. X            State = NORMAL;
  721. X            msg("");
  722. X            *Uncurschar = *Insstart;
  723. X            Undelchars = Ninsert;
  724. X            /* Undobuff[0] = '\0'; */
  725. X            /* construct the Redo buffer */
  726. X            p=Redobuff;
  727. X            q=Insbuff;
  728. X            while ( q < Insptr )
  729. X                *p++ = *q++;
  730. X            *p++ = ESC;
  731. X            *p = NUL;
  732. X            updatescreen();
  733. X            break;
  734. X
  735. X        case CTRL('D'):
  736. X            /*
  737. X             * Control-D is treated as a backspace in insert
  738. X             * mode to make auto-indent easier. This isn't
  739. X             * completely compatible with vi, but it's a lot
  740. X             * easier than doing it exactly right, and the
  741. X             * difference isn't very noticeable.
  742. X             */
  743. X        case BS:
  744. X            /* can't backup past starting point */
  745. X            if (Curschar->linep == Insstart->linep &&
  746. X                Curschar->index <= Insstart->index) {
  747. X                beep();
  748. X                break;
  749. X            }
  750. X
  751. X            /* can't backup to a previous line */
  752. X            if (Curschar->linep != Insstart->linep &&
  753. X                Curschar->index <= 0) {
  754. X                beep();
  755. X                break;
  756. X            }
  757. X
  758. X            did_ai = FALSE;
  759. X            dec(Curschar);
  760. X            delchar(TRUE);
  761. X            Insptr--;
  762. X            Ninsert--;
  763. X            cursupdate();
  764. X            updateline();
  765. X            break;
  766. X
  767. X        case CR:
  768. X        case NL:
  769. X            *Insptr++ = NL;
  770. X            Ninsert++;
  771. X            opencmd(FORWARD, TRUE);        /* open a new line */
  772. X            cursupdate();
  773. X            updatescreen();
  774. X            break;
  775. X
  776. X        default:
  777. X            did_ai = FALSE;
  778. X            insertchar(c);
  779. X            break;
  780. X        }
  781. X    }
  782. X    }
  783. X}
  784. X
  785. X/*
  786. X * Special characters in this context are those that need processing other
  787. X * than the simple insertion that can be performed here. This includes ESC
  788. X * which terminates the insert, and CR/NL which need special processing to
  789. X * open up a new line. This routine tries to optimize insertions performed
  790. X * by the "redo" command, so it needs to know when it should stop and defer
  791. X * processing to the "normal" mechanism.
  792. X */
  793. X#define    ISSPECIAL(c)    ((c) == NL || (c) == CR || (c) == ESC)
  794. X
  795. void
  796. insertchar(c)
  797. int c;
  798. X{
  799. X    char *p;
  800. X
  801. X    if ( ! anyinput() ) {
  802. X        inschar(c);
  803. X        *Insptr++ = c;
  804. X        Ninsert++;
  805. X        /*
  806. X         * The following kludge avoids overflowing the statically
  807. X         * allocated insert buffer. Just dump the user back into
  808. X         * command mode, and print a message.
  809. X         */
  810. X        if (Insptr+10 >= &Insbuff[1024]) {
  811. X            stuffin(mkstr(ESC));
  812. X            emsg("No buffer space - returning to command mode");
  813. X            sleep(2);
  814. X        }
  815. X    }
  816. X    else {
  817. X        /* If there's any pending input, grab it all at once. */
  818. X        p = Insptr;
  819. X        *Insptr++ = c;
  820. X        Ninsert++;
  821. X        for (c = vpeekc(); !ISSPECIAL(c) ;c = vpeekc()) {
  822. X            c = vgetc();
  823. X            *Insptr++ = c;
  824. X            Ninsert++;
  825. X        }
  826. X        *Insptr = '\0';
  827. X        insstr(p);
  828. X    }
  829. X    updateline();
  830. X}
  831. X
  832. void
  833. getout()
  834. X{
  835. X    windgoto(Rows-1,0);
  836. X    putchar('\r');
  837. X    putchar('\n');
  838. X    windexit(0);
  839. X}
  840. X
  841. void
  842. scrolldown(nlines)
  843. int nlines;
  844. X{
  845. X    register LPTR    *p;
  846. X    register int    done = 0;    /* total # of physical lines done */
  847. X
  848. X    /* Scroll up 'nlines' lines. */
  849. X    while (nlines--) {
  850. X        if ((p = prevline(Topchar)) == NULL)
  851. X            break;
  852. X        done += plines(p);
  853. X        *Topchar = *p;
  854. X        if (Curschar->linep == Botchar->linep->prev)
  855. X            *Curschar = *prevline(Curschar);
  856. X    }
  857. X    s_ins(0, done);
  858. X}
  859. X
  860. void
  861. scrollup(nlines)
  862. int nlines;
  863. X{
  864. X    register LPTR    *p;
  865. X    register int    done = 0;    /* total # of physical lines done */
  866. X    register int    pl;        /* # of plines for the current line */
  867. X
  868. X    /* Scroll down 'nlines' lines. */
  869. X    while (nlines--) {
  870. X        pl = plines(Topchar);
  871. X        if ((p = nextline(Topchar)) == NULL)
  872. X            break;
  873. X        done += pl;
  874. X        if (Curschar->linep == Topchar->linep)
  875. X            *Curschar = *p;
  876. X        *Topchar = *p;
  877. X
  878. X    }
  879. X    s_del(0, done);
  880. X}
  881. X
  882. X/*
  883. X * oneright
  884. X * oneleft
  885. X * onedown
  886. X * oneup
  887. X *
  888. X * Move one char {right,left,down,up}.  Return TRUE when
  889. X * sucessful, FALSE when we hit a boundary (of a line, or the file).
  890. X */
  891. X
  892. bool_t
  893. oneright()
  894. X{
  895. X    set_want_col = TRUE;
  896. X
  897. X    switch (inc(Curschar)) {
  898. X
  899. X    case 0:
  900. X        return TRUE;
  901. X
  902. X    case 1:
  903. X        dec(Curschar);        /* crossed a line, so back up */
  904. X        /* fall through */
  905. X    case -1:
  906. X        return FALSE;
  907. X    }
  908. X}
  909. X
  910. bool_t
  911. oneleft()
  912. X{
  913. X    set_want_col = TRUE;
  914. X
  915. X    switch (dec(Curschar)) {
  916. X
  917. X    case 0:
  918. X        return TRUE;
  919. X
  920. X    case 1:
  921. X        inc(Curschar);        /* crossed a line, so back up */
  922. X        /* fall through */
  923. X    case -1:
  924. X        return FALSE;
  925. X    }
  926. X}
  927. X
  928. void
  929. beginline(flag)
  930. bool_t    flag;
  931. X{
  932. X    while ( oneleft() )
  933. X        ;
  934. X    if (flag) {
  935. X        while (isspace(gchar(Curschar)) && oneright())
  936. X            ;
  937. X    }
  938. X    set_want_col = TRUE;
  939. X}
  940. X
  941. bool_t
  942. oneup(n)
  943. X{
  944. X    LPTR p, *np;
  945. X    int k;
  946. X
  947. X    p = *Curschar;
  948. X    for ( k=0; k<n; k++ ) {
  949. X        /* Look for the previous line */
  950. X        if ( (np=prevline(&p)) == NULL ) {
  951. X            /* If we've at least backed up a little .. */
  952. X            if ( k > 0 )
  953. X                break;    /* to update the cursor, etc. */
  954. X            else
  955. X                return FALSE;
  956. X        }
  957. X        p = *np;
  958. X    }
  959. X    *Curschar = p;
  960. X    /* This makes sure Topchar gets updated so the complete line */
  961. X    /* is one the screen. */
  962. X    cursupdate();
  963. X    /* try to advance to the column we want to be at */
  964. X    *Curschar = *coladvance(&p, Curswant);
  965. X    return TRUE;
  966. X}
  967. X
  968. bool_t
  969. onedown(n)
  970. X{
  971. X    LPTR p, *np;
  972. X    int k;
  973. X
  974. X    p = *Curschar;
  975. X    for ( k=0; k<n; k++ ) {
  976. X        /* Look for the next line */
  977. X        if ( (np=nextline(&p)) == NULL ) {
  978. X            if ( k > 0 )
  979. X                break;
  980. X            else
  981. X                return FALSE;
  982. X        }
  983. X        p = *np;
  984. X    }
  985. X    /* try to advance to the column we want to be at */
  986. X    *Curschar = *coladvance(&p, Curswant);
  987. X    return TRUE;
  988. X}
  989. END_OF_FILE
  990. if test 6480 -ne `wc -c <'edit.c'`; then
  991.     echo shar: \"'edit.c'\" unpacked with wrong size!
  992. fi
  993. # end of 'edit.c'
  994. fi
  995. if test -f 'help.c' -a "${1}" != "-c" ; then 
  996.   echo shar: Will not clobber existing file \"'help.c'\"
  997. else
  998. echo shar: Extracting \"'help.c'\" \(8348 characters\)
  999. sed "s/^X//" >'help.c' <<'END_OF_FILE'
  1000. X/*
  1001. X * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  1002. X *
  1003. X * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  1004. X *
  1005. X */
  1006. X
  1007. X#include "stevie.h"
  1008. X
  1009. char    *Version = "STEVIE - Version 3.10";
  1010. X
  1011. static    int    helprow;
  1012. X
  1013. X#ifdef    HELP
  1014. X
  1015. X#ifdef    MEGAMAX
  1016. overlay "help"
  1017. X#endif
  1018. X
  1019. static    void    longline();
  1020. X
  1021. bool_t
  1022. help()
  1023. X{
  1024. X
  1025. X/***********************************************************************
  1026. X * First Screen:   Positioning within file, Adjusting the Screen
  1027. X ***********************************************************************/
  1028. X
  1029. X    outstr(T_ED);
  1030. X    windgoto(helprow = 0, 0);
  1031. X
  1032. longline("\
  1033. X   Positioning within file\n\
  1034. X   =======================\n\
  1035. X      ^F             Forward screenfull             Original version by:\n\
  1036. X      ^B             Backward screenfull                Tim Thompson\n");
  1037. longline("\
  1038. X      ^D             scroll down half screen\n\
  1039. X      ^U             scroll up half screen          Extensive hacks by:\n");
  1040. longline("\
  1041. X      G              Goto line (end default)            Tony Andrews\n\
  1042. X      ]]             next function\n\
  1043. X      [[             previous function\n\
  1044. X      /re            next occurence of regular expression 're'\n");
  1045. longline("\
  1046. X      ?re            prior occurence of regular expression 're'\n\
  1047. X      n              repeat last / or ?\n\
  1048. X      N              reverse last / or ?\n\
  1049. X      %              find matching (, ), {, }, [, or ]\n");
  1050. longline("\
  1051. X\n\
  1052. X   Adjusting the screen\n\
  1053. X   ====================\n\
  1054. X      ^L             Redraw the screen\n\
  1055. X      ^E             scroll window down 1 line\n\
  1056. X      ^Y             scroll window up 1 line\n");
  1057. longline("\
  1058. X      z<RETURN>      redraw, current line at top\n\
  1059. X      z-             ... at bottom\n\
  1060. X      z.             ... at center\n");
  1061. X
  1062. X    windgoto(0, 52);
  1063. X    longline(Version);
  1064. X
  1065. X    windgoto(helprow = Rows-2, 47);
  1066. X    longline("<Press space bar to continue>\n");
  1067. X    windgoto(helprow = Rows-1, 47);
  1068. X    longline("<Any other key will quit>");
  1069. X
  1070. X    if ( vgetc() != ' ' )
  1071. X        return TRUE;
  1072. X
  1073. X/***********************************************************************
  1074. X * Second Screen:   Character positioning
  1075. X ***********************************************************************/
  1076. X
  1077. X    outstr(T_ED);
  1078. X    windgoto(helprow = 0, 0);
  1079. X
  1080. longline("\
  1081. X   Character Positioning\n\
  1082. X   =====================\n\
  1083. X      ^              first non-white\n\
  1084. X      0              beginning of line\n\
  1085. X      $              end of line\n\
  1086. X      h              backward\n");
  1087. longline("\
  1088. X      l              forward\n\
  1089. X      ^H             same as h\n\
  1090. X      space          same as l\n\
  1091. X      fx             find 'x' forward\n");
  1092. longline("\
  1093. X      Fx             find 'x' backward\n\
  1094. X      tx             upto 'x' forward\n\
  1095. X      Tx             upto 'x' backward\n\
  1096. X      ;              Repeat last f, F, t, or T\n");
  1097. longline("\
  1098. X      ,              inverse of ;\n\
  1099. X      |              to specified column\n\
  1100. X      %              find matching (, ), {, }, [, or ]\n");
  1101. X
  1102. X    windgoto(helprow = Rows-2, 47);
  1103. X    longline("<Press space bar to continue>\n");
  1104. X    windgoto(helprow = Rows-1, 47);
  1105. X    longline("<Any other key will quit>");
  1106. X
  1107. X    if ( vgetc() != ' ' )
  1108. X        return TRUE;
  1109. X
  1110. X/***********************************************************************
  1111. X * Third Screen:   Line Positioning, Marking and Returning
  1112. X ***********************************************************************/
  1113. X
  1114. X    outstr(T_ED);
  1115. X    windgoto(helprow = 0, 0);
  1116. X
  1117. longline("\
  1118. X    Line Positioning\n\
  1119. X    =====================\n\
  1120. X    H           home window line\n\
  1121. X    L           last window line\n\
  1122. X    M           middle window line\n");
  1123. longline("\
  1124. X    +           next line, at first non-white\n\
  1125. X    -           previous line, at first non-white\n\
  1126. X    CR          return, same as +\n\
  1127. X    j           next line, same column\n\
  1128. X    k           previous line, same column\n");
  1129. X
  1130. longline("\
  1131. X\n\
  1132. X    Marking and Returning\n\
  1133. X    =====================\n\
  1134. X    ``          previous context\n\
  1135. X    ''          ... at first non-white in line\n");
  1136. longline("\
  1137. X    mx          mark position with letter 'x'\n\
  1138. X    `x          to mark 'x'\n\
  1139. X    'x          ... at first non-white in line\n");
  1140. X
  1141. X    windgoto(helprow = Rows-2, 47);
  1142. X    longline("<Press space bar to continue>\n");
  1143. X    windgoto(helprow = Rows-1, 47);
  1144. X    longline("<Any other key will quit>");
  1145. X
  1146. X    if ( vgetc() != ' ' )
  1147. X        return TRUE;
  1148. X/***********************************************************************
  1149. X * Fourth Screen:   Insert & Replace, 
  1150. X ***********************************************************************/
  1151. X
  1152. X    outstr(T_ED);
  1153. X    windgoto(helprow = 0, 0);
  1154. X
  1155. longline("\
  1156. X    Insert and Replace\n\
  1157. X    ==================\n\
  1158. X    a           append after cursor\n\
  1159. X    i           insert before cursor\n\
  1160. X    A           append at end of line\n\
  1161. X    I           insert before first non-blank\n");
  1162. longline("\
  1163. X    o           open line below\n\
  1164. X    O           open line above\n\
  1165. X    rx          replace single char with 'x'\n\
  1166. X    R           replace characters (not yet)\n");
  1167. X
  1168. longline("\
  1169. X\n\
  1170. X    Words, sentences, paragraphs\n\
  1171. X    ============================\n\
  1172. X    w           word forward\n\
  1173. X    b           back word\n\
  1174. X    e           end of word\n\
  1175. X    )           to next sentence (not yet)\n\
  1176. X    }           to next paragraph (not yet)\n");
  1177. longline("\
  1178. X    (           back sentence (not yet)\n\
  1179. X    {           back paragraph (not yet)\n\
  1180. X    W           blank delimited word\n\
  1181. X    B           back W\n\
  1182. X    E           to end of W\n");
  1183. X
  1184. X    windgoto(helprow = Rows-2, 47);
  1185. X    longline("<Press space bar to continue>\n");
  1186. X    windgoto(helprow = Rows-1, 47);
  1187. X    longline("<Any other key will quit>");
  1188. X
  1189. X    if ( vgetc() != ' ' )
  1190. X        return TRUE;
  1191. X
  1192. X/***********************************************************************
  1193. X * Fifth Screen:   Misc. operations, 
  1194. X ***********************************************************************/
  1195. X
  1196. X    outstr(T_ED);
  1197. X    windgoto(helprow = 0, 0);
  1198. X
  1199. longline("\
  1200. X    Undo  &  Redo\n\
  1201. X    =============\n\
  1202. X    u           undo last change (partially done)\n\
  1203. X    U           restore current line (not yet)\n\
  1204. X    .           repeat last change\n");
  1205. X
  1206. longline("\
  1207. X\n\
  1208. X    File manipulation\n\
  1209. X    =================\n");
  1210. longline("\
  1211. X    :w          write back changes\n\
  1212. X    :wq         write and quit\n\
  1213. X    :x          write if modified, and quit\n\
  1214. X    :q          quit\n\
  1215. X    :q!         quit, discard changes\n\
  1216. X    :e name     edit file 'name'\n");
  1217. longline("\
  1218. X    :e!         reedit, discard changes\n\
  1219. X    :e #        edit alternate file\n\
  1220. X    :w name     write file 'name'\n");
  1221. longline("\
  1222. X    :n          edit next file in arglist\n\
  1223. X    :n args     specify new arglist (not yet)\n\
  1224. X    :rew        rewind arglist\n\
  1225. X    :f          show current file and lines\n");
  1226. longline("\
  1227. X    :f file     change current file name\n\
  1228. X    :ta tag     to tag file entry 'tag'\n\
  1229. X    ^]          :ta, current word is tag\n");
  1230. X
  1231. X    windgoto(helprow = Rows-2, 47);
  1232. X    longline("<Press space bar to continue>\n");
  1233. X    windgoto(helprow = Rows-1, 47);
  1234. X    longline("<Any other key will quit>");
  1235. X
  1236. X    if ( vgetc() != ' ' )
  1237. X        return TRUE;
  1238. X
  1239. X/***********************************************************************
  1240. X * Sixth Screen:   Operators, Misc. operations, Yank & Put
  1241. X ***********************************************************************/
  1242. X
  1243. X    outstr(T_ED);
  1244. X    windgoto(helprow = 0, 0);
  1245. X
  1246. longline("\
  1247. X    Operators (double to affect lines)\n\
  1248. X    ==================================\n\
  1249. X    d           delete\n\
  1250. X    c           change\n");
  1251. longline("\
  1252. X    <           left shift\n\
  1253. X    >           right shift\n\
  1254. X    y           yank to buffer\n");
  1255. X
  1256. longline("\n\
  1257. X    Miscellaneous operations\n\
  1258. X    ========================\n\
  1259. X    C           change rest of line\n\
  1260. X    D           delete rest of line\n\
  1261. X    s           substitute chars\n");
  1262. longline("\
  1263. X    S           substitute lines (not yet)\n\
  1264. X    J           join lines\n\
  1265. X    x           delete characters\n\
  1266. X    X           ... before cursor\n");
  1267. X
  1268. longline("\n\
  1269. X    Yank and Put\n\
  1270. X    ============\n\
  1271. X    p           put back text\n\
  1272. X    P           put before\n\
  1273. X    Y           yank lines");
  1274. X
  1275. X    windgoto(helprow = Rows-1, 47);
  1276. X    longline("<Press any key>");
  1277. X
  1278. X    vgetc();
  1279. X
  1280. X    return TRUE;
  1281. X}
  1282. X
  1283. static void
  1284. longline(p)
  1285. char *p;
  1286. X{
  1287. X    char *s;
  1288. X
  1289. X    for ( s = p; *s ;s++ ) {
  1290. X        if ( *s == '\n' )
  1291. X            windgoto(++helprow, 0);
  1292. X        else
  1293. X            outchar(*s);
  1294. X    }
  1295. X}
  1296. X#else
  1297. X
  1298. bool_t
  1299. help()
  1300. X{
  1301. X    msg("Sorry, help not configured");
  1302. X    return FALSE;
  1303. X}
  1304. X#endif
  1305. END_OF_FILE
  1306. if test 8348 -ne `wc -c <'help.c'`; then
  1307.     echo shar: \"'help.c'\" unpacked with wrong size!
  1308. fi
  1309. # end of 'help.c'
  1310. fi
  1311. if test -f 'main.c' -a "${1}" != "-c" ; then 
  1312.   echo shar: Will not clobber existing file \"'main.c'\"
  1313. else
  1314. echo shar: Extracting \"'main.c'\" \(6750 characters\)
  1315. sed "s/^X//" >'main.c' <<'END_OF_FILE'
  1316. X/*
  1317. X * STEVIE - ST Editor for VI Enthusiasts   ...Tim Thompson...twitch!tjt...
  1318. X *
  1319. X * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  1320. X *
  1321. X */
  1322. X
  1323. X#include "stevie.h"
  1324. X
  1325. int Rows;        /* Number of Rows and Columns */
  1326. int Columns;        /* in the current window. */
  1327. X
  1328. char *Realscreen = NULL;    /* What's currently on the screen, a single */
  1329. X                /* array of size Rows*Columns. */
  1330. char *Nextscreen = NULL;    /* What's to be put on the screen. */
  1331. X
  1332. char *Filename = NULL;    /* Current file name */
  1333. X
  1334. LPTR *Filemem;        /* The contents of the file, as a single array. */
  1335. X
  1336. LPTR *Fileend;        /* Pointer to the end of the file in Filemem. */
  1337. X            /* (It points to the byte AFTER the last byte.) */
  1338. X
  1339. LPTR *Topchar;        /* Pointer to the byte in Filemem which is */
  1340. X            /* in the upper left corner of the screen. */
  1341. X
  1342. LPTR *Botchar;        /* Pointer to the byte in Filemem which is */
  1343. X            /* just off the bottom of the screen. */
  1344. X
  1345. LPTR *Curschar;        /* Pointer to byte in Filemem at which the */
  1346. X            /* cursor is currently placed. */
  1347. X
  1348. int Cursrow, Curscol;    /* Current position of cursor */
  1349. X
  1350. int Cursvcol;        /* Current virtual column, the column number of */
  1351. X            /* the file's actual line, as opposed to the */
  1352. X            /* column number we're at on the screen.  This */
  1353. X            /* makes a difference on lines that span more */
  1354. X            /* than one screen line. */
  1355. X
  1356. int Curswant = 0;    /* The column we'd like to be at. This is used */
  1357. X            /* try to stay in the same column through up/down */
  1358. X            /* cursor motions. */
  1359. X
  1360. bool_t set_want_col;    /* If set, then update Curswant the next time */
  1361. X            /* through cursupdate() to the current virtual */
  1362. X            /* column. */
  1363. X
  1364. int State = NORMAL;    /* This is the current state of the command */
  1365. X            /* interpreter. */
  1366. X
  1367. int Prenum = 0;        /* The (optional) number before a command. */
  1368. X
  1369. LPTR *Insstart;        /* This is where the latest insert/append */
  1370. X            /* mode started. */
  1371. X
  1372. bool_t Changed = 0;    /* Set to 1 if something in the file has been */
  1373. X            /* changed and not written out. */
  1374. X
  1375. bool_t Debug = 0;
  1376. X
  1377. char Redobuff[1024];    /* Each command should stuff characters into this */
  1378. X            /* buffer that will re-execute itself. */
  1379. X
  1380. char Undobuff[1024];    /* Each command should stuff characters into this */
  1381. X            /* buffer that will undo its effects. */
  1382. X
  1383. char Insbuff[1024];    /* Each insertion gets stuffed into this buffer. */
  1384. X
  1385. LPTR *Uncurschar;    /* Curschar is restored to this before undoing. */
  1386. X
  1387. int Ninsert = 0;    /* Number of characters in the current insertion. */
  1388. int Undelchars = 0;    /* Number of characters to delete, when undoing. */
  1389. char *Insptr = NULL;
  1390. X
  1391. char **files;        /* list of input files */
  1392. int  numfiles;        /* number of input files */
  1393. int  curfile;        /* number of the current file */
  1394. X
  1395. static void
  1396. usage()
  1397. X{
  1398. X    fprintf(stderr, "usage: stevie [file ...]\n");
  1399. X    fprintf(stderr, "       stevie -t tag\n");
  1400. X    fprintf(stderr, "       stevie +[num] file\n");
  1401. X    fprintf(stderr, "       stevie +/pat  file\n");
  1402. X    exit(1);
  1403. X}
  1404. X
  1405. main(argc,argv)
  1406. int    argc;
  1407. char    *argv[];
  1408. X{
  1409. X    char    *initstr, *getenv();    /* init string from the environment */
  1410. X    char    *tag = NULL;        /* tag from command line */
  1411. X    char    *pat = NULL;        /* pattern from command line */
  1412. X    int    line = -1;        /* line number from command line */
  1413. X
  1414. X    /*
  1415. X     * Process the command line arguments.
  1416. X     */
  1417. X    if (argc > 1) {
  1418. X        switch (argv[1][0]) {
  1419. X        
  1420. X        case '-':            /* -t tag */
  1421. X            if (argv[1][1] != 't')
  1422. X                usage();
  1423. X
  1424. X            if (argv[2] == NULL)
  1425. X                usage();
  1426. X
  1427. X            Filename = NULL;
  1428. X            tag = argv[2];
  1429. X            numfiles = 1;
  1430. X            break;
  1431. X
  1432. X        case '+':            /* +n or +/pat */
  1433. X            if (argv[1][1] == '/') {
  1434. X                if (argv[2] == NULL)
  1435. X                    usage();
  1436. X                Filename = strsave(argv[2]);
  1437. X                pat = &(argv[1][1]);
  1438. X                numfiles = 1;
  1439. X
  1440. X            } else if (isdigit(argv[1][1]) || argv[1][1] == NUL) {
  1441. X                if (argv[2] == NULL)
  1442. X                    usage();
  1443. X                Filename = strsave(argv[2]);
  1444. X                numfiles = 1;
  1445. X
  1446. X                line = (isdigit(argv[1][1])) ?
  1447. X                    atoi(&(argv[1][1])) : 0;
  1448. X            } else
  1449. X                usage();
  1450. X
  1451. X            break;
  1452. X
  1453. X        default:            /* must be a file name */
  1454. X            Filename = strsave(argv[1]);
  1455. X            files = &(argv[1]);
  1456. X            numfiles = argc - 1;
  1457. X            break;
  1458. X        }
  1459. X    } else {
  1460. X        Filename = NULL;
  1461. X        numfiles = 1;
  1462. X    }
  1463. X    curfile = 0;
  1464. X
  1465. X    windinit();
  1466. X
  1467. X    /*
  1468. X     * Allocate LPTR structures for all the various position pointers
  1469. X     */
  1470. X    if ((Filemem = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
  1471. X        fprintf(stderr, "Can't allocate data structures\n");
  1472. X        windexit(0);
  1473. X    }
  1474. X    if ((Fileend = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
  1475. X        fprintf(stderr, "Can't allocate data structures\n");
  1476. X        windexit(0);
  1477. X    }
  1478. X    if ((Topchar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
  1479. X        fprintf(stderr, "Can't allocate data structures\n");
  1480. X        windexit(0);
  1481. X    }
  1482. X    if ((Botchar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
  1483. X        fprintf(stderr, "Can't allocate data structures\n");
  1484. X        windexit(0);
  1485. X    }
  1486. X    if ((Curschar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
  1487. X        fprintf(stderr, "Can't allocate data structures\n");
  1488. X        windexit(0);
  1489. X    }
  1490. X    if ((Insstart = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
  1491. X        fprintf(stderr, "Can't allocate data structures\n");
  1492. X        windexit(0);
  1493. X    }
  1494. X    if ((Uncurschar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
  1495. X        fprintf(stderr, "Can't allocate data structures\n");
  1496. X        windexit(0);
  1497. X    }
  1498. X
  1499. X    screenalloc();
  1500. X    filealloc();        /* Initialize Filemem & Fileend */
  1501. X
  1502. X    screenclear();
  1503. X
  1504. X    if ((initstr = getenv("EXINIT")) != NULL) {
  1505. X        char *lp, buf[128];
  1506. X
  1507. X        if ((lp = getenv("LINES")) != NULL) {
  1508. X            sprintf(buf, "%s lines=%s", initstr, lp);
  1509. X            readcmdline(':', buf);
  1510. X        } else
  1511. X            readcmdline(':', initstr);
  1512. X    }
  1513. X
  1514. X    if (Filename != NULL) {
  1515. X        if (readfile(Filename, Filemem, FALSE))
  1516. X            filemess("[New File]");
  1517. X    } else
  1518. X        msg("Empty Buffer");
  1519. X
  1520. X    setpcmark();
  1521. X
  1522. X    updatescreen();
  1523. X    
  1524. X    if (tag) {
  1525. X        stuffin(":ta ");
  1526. X        stuffin(tag);
  1527. X        stuffin("\n");
  1528. X
  1529. X    } else if (pat) {
  1530. X        stuffin(pat);
  1531. X        stuffin("\n");
  1532. X
  1533. X    } else if (line >= 0) {
  1534. X        if (line > 0)
  1535. X            stuffnum(line);
  1536. X        stuffin("G");
  1537. X    }
  1538. X
  1539. X    edit();
  1540. X
  1541. X    windexit(0);
  1542. X}
  1543. X
  1544. X#define    RBSIZE    1280        /* should be a little bigger than YBSIZE */
  1545. static char getcbuff[RBSIZE];
  1546. static char *getcnext = NULL;
  1547. X
  1548. void
  1549. stuffin(s)
  1550. char *s;
  1551. X{
  1552. X    if ( getcnext == NULL ) {
  1553. X        strcpy(getcbuff,s);
  1554. X        getcnext = getcbuff;
  1555. X    } else
  1556. X        strcat(getcbuff,s);
  1557. X}
  1558. X
  1559. void
  1560. stuffnum(n)
  1561. int    n;
  1562. X{
  1563. X    char    buf[32];
  1564. X
  1565. X    sprintf(buf, "%d", n);
  1566. X    stuffin(buf);
  1567. X}
  1568. X
  1569. void
  1570. addtobuff(s,c1,c2,c3,c4,c5,c6)
  1571. char *s;
  1572. char c1, c2, c3, c4, c5, c6;
  1573. X{
  1574. X    char *p = s;
  1575. X    if ( (*p++ = c1) == NUL )
  1576. X        return;
  1577. X    if ( (*p++ = c2) == NUL )
  1578. X        return;
  1579. X    if ( (*p++ = c3) == NUL )
  1580. X        return;
  1581. X    if ( (*p++ = c4) == NUL )
  1582. X        return;
  1583. X    if ( (*p++ = c5) == NUL )
  1584. X        return;
  1585. X    if ( (*p++ = c6) == NUL )
  1586. X        return;
  1587. X}
  1588. X
  1589. int
  1590. vgetc()
  1591. X{
  1592. X    if ( getcnext != NULL ) {
  1593. X        int nextc = *getcnext++;
  1594. X        if ( *getcnext == NUL ) {
  1595. X            *getcbuff = NUL;
  1596. X            getcnext = NULL;
  1597. X        }
  1598. X        return(nextc);
  1599. X    }
  1600. X    return(inchar());
  1601. X}
  1602. X
  1603. int
  1604. vpeekc()
  1605. X{
  1606. X    if ( getcnext != NULL )
  1607. X        return(*getcnext);
  1608. X    return(-1);
  1609. X}
  1610. X
  1611. X/*
  1612. X * anyinput
  1613. X *
  1614. X * Return non-zero if input is pending.
  1615. X */
  1616. X
  1617. bool_t
  1618. anyinput()
  1619. X{
  1620. X    return (getcnext != NULL);
  1621. X}
  1622. END_OF_FILE
  1623. if test 6750 -ne `wc -c <'main.c'`; then
  1624.     echo shar: \"'main.c'\" unpacked with wrong size!
  1625. fi
  1626. # end of 'main.c'
  1627. fi
  1628. if test -f 'misccmds.c' -a "${1}" != "-c" ; then 
  1629.   echo shar: Will not clobber existing file \"'misccmds.c'\"
  1630. else
  1631. echo shar: Extracting \"'misccmds.c'\" \(8039 characters\)
  1632. sed "s/^X//" >'misccmds.c' <<'END_OF_FILE'
  1633. X/*
  1634. X * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  1635. X *
  1636. X * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  1637. X *
  1638. X */
  1639. X
  1640. X#include "stevie.h"
  1641. X
  1642. static    void    openfwd(), openbwd();
  1643. X
  1644. extern    int    did_ai;
  1645. X
  1646. X/*
  1647. X * opencmd
  1648. X *
  1649. X * Add a blank line above or below the current line.
  1650. X */
  1651. X
  1652. void
  1653. opencmd(dir, can_ai)
  1654. int    dir;
  1655. int    can_ai;            /* if true, consider auto-indent */
  1656. X{
  1657. X    if (dir == FORWARD)
  1658. X        openfwd(can_ai);
  1659. X    else
  1660. X        openbwd(can_ai);
  1661. X}
  1662. X
  1663. static void
  1664. openfwd(can_ai)
  1665. int    can_ai;
  1666. X{
  1667. X    LINE    *l;
  1668. X    LPTR    *next;
  1669. X    char    *s;        /* string to be moved to new line, if any */
  1670. X
  1671. X    /*
  1672. X     * If we're in insert mode, we need to move the remainder of the
  1673. X     * current line onto the new line. Otherwise the new line is left
  1674. X     * blank.
  1675. X     */
  1676. X    if (State == INSERT)
  1677. X        s = &Curschar->linep->s[Curschar->index];
  1678. X    else
  1679. X        s = "";
  1680. X
  1681. X    if ((next = nextline(Curschar)) == NULL)    /* open on last line */
  1682. X        next = Fileend;
  1683. X
  1684. X    /*
  1685. X     * By asking for as much space as the prior line had we make sure
  1686. X     * that we'll have enough space for any auto-indenting.
  1687. X     */
  1688. X    if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
  1689. X        return;
  1690. X
  1691. X    if (*s != NUL)
  1692. X        strcpy(l->s, s);        /* copy string to new line */
  1693. X#if 0
  1694. X    else if (can_ai && P(P_AI)) {
  1695. X        /*
  1696. X         * Auto-indent removed due to buggy implementation...
  1697. X         */
  1698. X         did_ai = TRUE;
  1699. X    }
  1700. X#endif
  1701. X
  1702. X    if (State == INSERT)        /* truncate current line at cursor */
  1703. X        *s = NUL;
  1704. X            
  1705. X
  1706. X    Curschar->linep->next = l;    /* link neighbors to new line */
  1707. X    next->linep->prev = l;
  1708. X
  1709. X    l->prev = Curschar->linep;    /* link new line to neighbors */
  1710. X    l->next = next->linep;
  1711. X
  1712. X    if (next == Fileend)            /* new line at end */
  1713. X        l->num = Curschar->linep->num + LINEINC;
  1714. X
  1715. X    else if ((l->prev->num) + 1 == l->next->num)    /* no gap, renumber */
  1716. X        renum();
  1717. X
  1718. X    else {                    /* stick it in the middle */
  1719. X        unsigned long    lnum;
  1720. X        lnum = ((long)l->prev->num + (long)l->next->num) / 2;
  1721. X        l->num = lnum;
  1722. X    }
  1723. X
  1724. X    *Curschar = *nextline(Curschar);    /* cursor moves down */
  1725. X    Curschar->index = 0;
  1726. X
  1727. X    s_ins(Cursrow+1, 1);    /* insert a physical line */
  1728. X
  1729. X    updatescreen();        /* because Botchar is now invalid... */
  1730. X
  1731. X    cursupdate();        /* update Cursrow before insert */
  1732. X}
  1733. X
  1734. static void
  1735. openbwd(can_ai)
  1736. int    can_ai;
  1737. X{
  1738. X    LINE    *l;
  1739. X    LPTR    *prev;
  1740. X
  1741. X    prev = prevline(Curschar);
  1742. X
  1743. X    if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
  1744. X        return;
  1745. X
  1746. X    Curschar->linep->prev = l;    /* link neighbors to new line */
  1747. X    if (prev != NULL)
  1748. X        prev->linep->next = l;
  1749. X
  1750. X    l->next = Curschar->linep;    /* link new line to neighbors */
  1751. X    if (prev != NULL)
  1752. X        l->prev = prev->linep;
  1753. X
  1754. X#if 0
  1755. X    if (can_ai && P(P_AI)) {
  1756. X        did_ai = TRUE;
  1757. X    }
  1758. X#endif
  1759. X
  1760. X    *Curschar = *prevline(Curschar);    /* cursor moves up */
  1761. X    Curschar->index = 0;
  1762. X
  1763. X    if (prev == NULL)            /* new start of file */
  1764. X        Filemem->linep = l;
  1765. X
  1766. X    renum();    /* keep it simple - we don't do this often */
  1767. X
  1768. X    cursupdate();            /* update Cursrow before insert */
  1769. X    if (Cursrow != 0)
  1770. X        s_ins(Cursrow, 1);        /* insert a physical line */
  1771. X
  1772. X    updatescreen();
  1773. X}
  1774. X
  1775. int
  1776. cntllines(pbegin,pend)
  1777. LPTR *pbegin, *pend;
  1778. X{
  1779. X    LINE *lp;
  1780. X    int lnum = 1;
  1781. X
  1782. X    for (lp = pbegin->linep; lp != pend->linep ;lp = lp->next)
  1783. X        lnum++;
  1784. X
  1785. X    return(lnum);
  1786. X}
  1787. X
  1788. X/*
  1789. X * plines(p) - return the number of physical screen lines taken by line 'p'
  1790. X */
  1791. int
  1792. plines(p)
  1793. LPTR    *p;
  1794. X{
  1795. X    register int    col;
  1796. X    register char    *s;
  1797. X
  1798. X    s = p->linep->s;
  1799. X
  1800. X    if (*s == NUL)        /* empty line */
  1801. X        return 1;
  1802. X
  1803. X    /*
  1804. X     * If list mode is on, then the '$' at the end of
  1805. X     * the line takes up one extra column.
  1806. X     */
  1807. X    col = P(P_LS) ? 1 : 0;
  1808. X
  1809. X    for (; *s != NUL ;s++) {
  1810. X        if ( *s == TAB && !P(P_LS))
  1811. X            col += P(P_TS) - (col % P(P_TS));
  1812. X        else
  1813. X            col += chars[(unsigned)(*s & 0xff)].ch_size;
  1814. X    }
  1815. X    return ((col + (Columns-1)) / Columns);
  1816. X}
  1817. X
  1818. void
  1819. fileinfo()
  1820. X{
  1821. X    long    l1, l2;
  1822. X    char    buf[80];
  1823. X
  1824. X    if (bufempty()) {
  1825. X        msg("Buffer Empty");
  1826. X        return;
  1827. X    }
  1828. X
  1829. X    l1 = cntllines(Filemem, Curschar);
  1830. X    l2 = cntllines(Filemem, Fileend) - 1;
  1831. X    sprintf(buf, "\"%s\"%s line %ld of %ld -- %ld %% --",
  1832. X        (Filename != NULL) ? Filename : "No File",
  1833. X        Changed ? " [Modified]" : "",
  1834. X        l1, l2, (l1 * 100)/l2);
  1835. X    msg(buf);
  1836. X}
  1837. X
  1838. X/*
  1839. X * gotoline(n) - return a pointer to line 'n'
  1840. X *
  1841. X * Returns a pointer to the last line of the file if n is zero, or
  1842. X * beyond the end of the file.
  1843. X */
  1844. LPTR *
  1845. gotoline(n)
  1846. int n;
  1847. X{
  1848. X    static    LPTR    l;
  1849. X
  1850. X    l.index = 0;
  1851. X
  1852. X    if ( n == 0 )
  1853. X        l = *prevline(Fileend);
  1854. X    else {
  1855. X        LPTR    *p;
  1856. X
  1857. X        for (l = *Filemem; --n > 0 ;l = *p)
  1858. X            if ((p = nextline(&l)) == NULL)
  1859. X                break;
  1860. X    }
  1861. X    return &l;
  1862. X}
  1863. X
  1864. void
  1865. inschar(c)
  1866. int    c;
  1867. X{
  1868. X    register char    *p, *pend;
  1869. X
  1870. X    /* make room for the new char. */
  1871. X    if ( ! canincrease(1) )
  1872. X        return;
  1873. X
  1874. X    p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
  1875. X    pend = &Curschar->linep->s[Curschar->index];
  1876. X
  1877. X    for (; p > pend ;p--)
  1878. X        *p = *(p-1);
  1879. X
  1880. X    *p = c;
  1881. X
  1882. X    /*
  1883. X     * If we're in insert mode and showmatch mode is set, then
  1884. X     * check for right parens and braces. If there isn't a match,
  1885. X     * then beep. If there is a match AND it's on the screen, then
  1886. X     * flash to it briefly. If it isn't on the screen, don't do anything.
  1887. X     */
  1888. X    if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) {
  1889. X        LPTR    *lpos, csave;
  1890. X
  1891. X        if ((lpos = showmatch()) == NULL)    /* no match, so beep */
  1892. X            beep();
  1893. X        else if (LINEOF(lpos) >= LINEOF(Topchar)) {
  1894. X            updatescreen();        /* show the new char first */
  1895. X            csave = *Curschar;
  1896. X            *Curschar = *lpos;    /* move to matching char */
  1897. X            cursupdate();
  1898. X            windgoto(Cursrow, Curscol);
  1899. X            delay();        /* brief pause */
  1900. X            *Curschar = csave;    /* restore cursor position */
  1901. X            cursupdate();
  1902. X        }
  1903. X    }
  1904. X
  1905. X    inc(Curschar);
  1906. X    CHANGED;
  1907. X}
  1908. X
  1909. void
  1910. insstr(s)
  1911. register char *s;
  1912. X{
  1913. X    register char *p, *endp;
  1914. X    register int k, n = strlen(s);
  1915. X
  1916. X    /* Move everything in the file over to make */
  1917. X    /* room for the new string. */
  1918. X    if (!canincrease(n))
  1919. X        return;
  1920. X
  1921. X    endp = &Curschar->linep->s[Curschar->index];
  1922. X    p = Curschar->linep->s + strlen(Curschar->linep->s) + 1 + n;
  1923. X
  1924. X    for (; p>endp ;p--)
  1925. X        *p = *(p-n);
  1926. X
  1927. X    p = &Curschar->linep->s[Curschar->index];
  1928. X    for ( k=0; k<n; k++ ) {
  1929. X        *p++ = *s++;
  1930. X        inc(Curschar);
  1931. X    }
  1932. X    CHANGED;
  1933. X}
  1934. X
  1935. bool_t
  1936. delchar(fixpos)
  1937. bool_t    fixpos;        /* if TRUE, fix the cursor position when done */
  1938. X{
  1939. X    register int i;
  1940. X
  1941. X    /* Check for degenerate case; there's nothing in the file. */
  1942. X    if (bufempty())
  1943. X        return FALSE;
  1944. X
  1945. X    if (lineempty())    /* can't do anything */
  1946. X        return FALSE;
  1947. X
  1948. X    /* Delete the char. at Curschar by shifting everything */
  1949. X    /* in the line down. */
  1950. X    for ( i=Curschar->index+1; i < Curschar->linep->size ;i++)
  1951. X        Curschar->linep->s[i-1] = Curschar->linep->s[i];
  1952. X
  1953. X    /* If we just took off the last character of a non-blank line, */
  1954. X    /* we don't want to end up positioned at the newline. */
  1955. X    if (fixpos) {
  1956. X        if (gchar(Curschar)==NUL && Curschar->index>0 && State!=INSERT)
  1957. X            Curschar->index--;
  1958. X    }
  1959. X    CHANGED;
  1960. X
  1961. X    return TRUE;
  1962. X}
  1963. X
  1964. X
  1965. void
  1966. delline(nlines)
  1967. X{
  1968. X    register LINE *p, *q;
  1969. X    int    doscreen = TRUE;    /* if true, update the screen */
  1970. X
  1971. X    /*
  1972. X     * There's no point in keeping the screen updated if we're
  1973. X     * deleting more than a screen's worth of lines.
  1974. X     */
  1975. X    if (nlines > (Rows - 1)) {
  1976. X        doscreen = FALSE;
  1977. X        s_del(Cursrow, Rows-1);    /* flaky way to clear rest of screen */
  1978. X    }
  1979. X
  1980. X    while ( nlines-- > 0 ) {
  1981. X
  1982. X        if (bufempty())            /* nothing to delete */
  1983. X            break;
  1984. X
  1985. X        if (buf1line()) {        /* just clear the line */
  1986. X            Curschar->linep->s[0] = NUL;
  1987. X            Curschar->index = 0;
  1988. X            break;
  1989. X        }
  1990. X
  1991. X        p = Curschar->linep->prev;
  1992. X        q = Curschar->linep->next;
  1993. X
  1994. X        if (p == NULL) {        /* first line of file so... */
  1995. X            Filemem->linep = q;    /* adjust start of file */
  1996. X            Topchar->linep = q;    /* and screen */
  1997. X        } else
  1998. X            p->next = q;
  1999. X        q->prev = p;
  2000. X
  2001. X        clrmark(Curschar->linep);    /* clear marks for the line */
  2002. X
  2003. X        /*
  2004. X         * Delete the correct number of physical lines on the screen
  2005. X         */
  2006. X        if (doscreen)
  2007. X            s_del(Cursrow, plines(Curschar));
  2008. X
  2009. X        /*
  2010. X         * If deleting the top line on the screen, adjust Topchar
  2011. X         */
  2012. X        if (Topchar->linep == Curschar->linep)
  2013. X            Topchar->linep = q;
  2014. X
  2015. X        free(Curschar->linep->s);
  2016. X        free(Curschar->linep);
  2017. X
  2018. X        Curschar->linep = q;
  2019. X        Curschar->index = 0;        /* is this right? */
  2020. X        CHANGED;
  2021. X
  2022. X        /* If we delete the last line in the file, back up */
  2023. X        if ( Curschar->linep == Fileend->linep) {
  2024. X            Curschar->linep = Curschar->linep->prev;
  2025. X            /* and don't try to delete any more lines */
  2026. X            break;
  2027. X        }
  2028. X    }
  2029. X}
  2030. END_OF_FILE
  2031. if test 8039 -ne `wc -c <'misccmds.c'`; then
  2032.     echo shar: \"'misccmds.c'\" unpacked with wrong size!
  2033. fi
  2034. # end of 'misccmds.c'
  2035. fi
  2036. echo shar: End of archive 2 \(of 4\).
  2037. cp /dev/null ark2isdone
  2038. MISSING=""
  2039. for I in 1 2 3 4 ; do
  2040.     if test ! -f ark${I}isdone ; then
  2041.     MISSING="${MISSING} ${I}"
  2042.     fi
  2043. done
  2044. if test "${MISSING}" = "" ; then
  2045.     echo You have unpacked all 4 archives.
  2046.     rm -f ark[1-9]isdone
  2047. else
  2048.     echo You still need to unpack the following archives:
  2049.     echo "        " ${MISSING}
  2050. fi
  2051. ##  End of shell archive.
  2052. exit 0
  2053.